package com.liuwei.spring.cloud.configuration;

import com.liuwei.spring.cloud.biz.support.GlobalExceptionUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author : evan.liu
 * @version V1.0
 * @Description: TODO
 * @date Date : 2022年04月26日 6:06 下午
 */
@EnableAsync
@Configuration
public class GlobalAsyncConfiguration extends AsyncConfigurerSupport {

    /**
     * Executor 用于执行 @async 方法; 如果我们不自定义异步方法的线程池，则默认使用的是 SimpleAsyncTaskExecutor
     * The Executor instance to be used when processing async method invocations.
     * @return 线程池
     */
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //核心线程池大小
        executor.setCorePoolSize(5);
        //最大线程数
        executor.setMaxPoolSize(20);
        //活跃时间
        executor.setKeepAliveSeconds(300);
        //队列容量
        executor.setQueueCapacity(50);
        //线程名字前缀
        executor.setThreadNamePrefix("TaskExecutePool-");
        // setRejectedExecutionHandler：当pool已经达到max size的时候，如何处理新任务
        // CallerRunsPolicy：不在新线程中执行任务，而是由调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.initialize();
        return executor;

        //ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10));
        //LinkedBlockingQueue blockingQueue = new LinkedBlockingQueue<>(10);
    }

    /**
     * 统一处理异常
     * @return
     */
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new AsyncExceptionHandler();
    }

    @Slf4j
    public static class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
        @Override
        public void handleUncaughtException(Throwable ex, Method method, Object... params) {
            log.error("Async|error:{}", ex.getMessage(),ex);
            GlobalExceptionUtils.handleGlobalException(ex);
            // 发送飞书消息
            /*if(!ApplicationHelper.getBean(GlobalDefaultConfig.class).getSystem_exception_warning_black_class().contains(ex.getClass().getName())){
                ApplicationHelper.getBean(IDingRobot.class).notice(ex);
            }*/
        }
    }
}
